package cn.edu.thu.tsquality.core.algorithm.linear.repair;

import cn.edu.thu.tsquality.core.common.algorithm.IAlgorithm;
import cn.edu.thu.tsquality.core.common.table.Header;
import cn.edu.thu.tsquality.core.common.table.Row;
import cn.edu.thu.tsquality.core.common.table.Table;
import scala.Serializable;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

// 线性修复：
// 找到每一段需要修复的数据，下标i到j，那么前后不需要修复的数据下标为i-1和j+1
// 将i到j的数据修复到(i-1)时刻到(j+1)时刻数据的那条直线上
public class LinearRepair implements IAlgorithm, Serializable
{
    LinearRepair()
    {
    }

    void println(String str)
    {
        System.out.println(str);
    }

    void print(String str)
    {
        System.out.print(str);
    }

    public Table run(Table table)
    {

        List tableAttrList = Arrays.asList(table.getHeader().toArray());
        if (tableAttrList.size() !=1 && tableAttrList.size()!= 2)
            throw new IllegalArgumentException("table columns error, expected 1/2 columns");
        List<Row> tableRowsList = table.getRows();
        int inputDataSize = tableRowsList.size();

        double[] attrData = new double[inputDataSize];
        boolean[] needRepair = new boolean[inputDataSize];

        // 标记需要修复的数据
        for (int i = 0; i < inputDataSize; i++)
        {
            // 第一列为空值或第二列值不为0，需要修复
            if (tableRowsList.get(i).get(0).equals(""))
            {
                attrData[i] = 0.0;
                needRepair[i] = true;
            }
            else
            {
                attrData[i] = Double.parseDouble((String) tableRowsList.get(i).get(0));
                if (table.getHeader().size() == 2 && Integer.parseInt((String) tableRowsList.get(i).get(1)) != 0)
                    needRepair[i] = true;
                else
                    needRepair[i] = false;

            }
        }

        //----------------
//        println(tableAttrList.toString());
//        println(inputDataSize+"");
//        print("data = [");
//        for(Double i : attrData)
//            print(i+" ");
//        println("]");
        //-----------------


        // 定义返回数据
        Header returnHeader = new Header(new String[] { (String)tableAttrList.get(0), "cleaned_"+tableAttrList.get(0)});
        List<Row> returnRows = new ArrayList<>();




        // 记录前后不需要修复的值。如果第一个值就需要修复，那么认为前面不需要修复的值为第一个值
        double previous = attrData[0], next = previous;

        // 确定需要修复的左端点i
        for(int i = 0; i < inputDataSize; )
        {
            if (needRepair[i])
            {
                // 确定需要修复的右端点j
                for (int j = i + 1; j <= inputDataSize; j++)
                    if (j == inputDataSize || !needRepair[j])
                    {
                        if (j == inputDataSize)
                            next = previous;
                        else
                            next = attrData[j];

                        // 修复
                        for (int k = 0; k < j - i; k++)
                        {
                            attrData[i + k] = previous + (next - previous) * (k + 1) / (j - i + 1);
                            returnRows.add(new Row(returnHeader, new String[] {
                                    (String)tableRowsList.get(i+k).get(0),
                                    String.format("%.3f", attrData[i+k])}, i+k));
                        }
                        i = j;
                        break;
                    }
            }
            else
            {
                returnRows.add(new Row(returnHeader, new String[] {
                        (String)tableRowsList.get(i).get(0),
                        String.format("%.3f", attrData[i])}, i));
                previous = attrData[i];
                i++;
            }


        }
        return new Table(returnHeader, returnRows);
    }
}